Shop OBEX P1 Docs P2 Docs Learn Events
Compiling LLVM for P2 on Windows (it works!) — Parallax Forums

Compiling LLVM for P2 on Windows (it works!)

RaymanRayman Posts: 16,302
edited 2026-04-15 22:46 in Propeller 2

Supposedly this can work and have made a bit of progress:

Note: This may be all wrong!
Note2: This is probably a lot easier in Linux or Mac...

Install Visual Studio

  • Add C++ Clange tools for Windows
  • Add latest Win 11 SDK

Install Python
Install CMake
Install Git

Download LLVM P2
Extract "llvm-project-XXX" to somewhere
Create "build" folder under this folder

Run cmake, maybe like this:
cmake -G "Visual Studio 18 2026" -A x64 -Thost=x64 -DCMAKE_INSTALL_PREFIX=/opt/p2llvm -DLLVM_ENABLE_PROJECTS="lld;clang" -DCMAKE_BUILD_TYPE=Release -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=P2 -DLLVM_TARGETS_TO_BUILD="" ../llvm-project/llvm

Use Visual Studio to open "LLVM.slnx" solution.
Build solution. (takes forever)

Find clang.exe under \build\Release\bin

try to build something like:
clang -Os -ffunction-sections -fdata-sections -fno-jump-tables --target=p2 -I .\libc\include -I .\ -o hello.o -c hello.c

Here's where I'm stuck... Got a .o file but the linker doesn't seem to work :{

Update: Seems all needed was two .a files (gifted from @rogloh ) to make it work. Had no luck generating these myself in either Windows or Linux. Maybe build instructions for these are out of date or something…

«1

Comments

  • RaymanRayman Posts: 16,302

    Ok, starting over, something is horribly wrong...

  • On windows 10 or 11 you can install WSL to get an emulated Linux shell, which probably has higher chance of success with this sort of thing. Getting anything to work with CMake on windows is a hassle, even if it's not a massive project like LLVM.

  • RaymanRayman Posts: 16,302

    It might be hopeless... Tried again and can compile but not link (again)...

  • RaymanRayman Posts: 16,302

    Found something from 4 years ago where @iseries and maybe me? Got it working in windows …

    https://forums.parallax.com/discussion/171962/llvm-backend-for-propeller-2/p5

    Will try stuff in post #133 there next…

  • roglohrogloh Posts: 6,331
    edited 2026-04-13 07:18

    For linking as a separate step I tend to use Clang twice, with these options:

    1) first compile only to get the .o file:
    clang -c -Os -ffunction-sections -fdata-sections -fno-jump-tables --target=p2 -I .\libc\include -I .\ -o hello.o -c hello.c

    2) then link the .o to the .elf (you can combine multiple .o files here too if needed)
    clang -v -Wl,-error-limit=0 -L /Users/roger/Applications/p2llvm/libp2/lib --target=p2 -Wl,--gc-sections -o hello.elf -Wl,--no-whole-archive -L /Users/roger/Applications/p2llvm/libc/lib hello.o

    -v prints actual linker options out,
    -Wl,-error-limit=0 prints multiple errors before failing,
    --target=p2 (P2 specific output)
    -Wl,gc-sections passes --gc-sections to lld linker
    -L /path/to/libs (use your path)
    -Wl,--no-whole-archive (doesn't suck in the entire lib.a code when only a single function is accessed)

    3) use loadp2 to send the .elf file to a P2 (it understands .elfs as well as binary files)
    loadp2 -PATCH -f 160000000 -b 115200 -t hello.elf

    You can also convert the .elf into a binary file if you want with this:
    llvm-objcopy -O binary -j .text -j .rodata -j .data hello.elf hello.bin

    Note this binary also needs to be patched when downloaded with loadp2 as I'm not sure that the LLVM toolchain building the startup code uses useful default startup frequencies or baud rates otherwise. I think it defaults to RCslow unless you call _clkset and _uart_init with some arguments. But if the binary is patched at the normal addresses it will use the desired values.

  • RaymanRayman Posts: 16,302

    @rogloh Yeah, but it didn't work... Using Clang twice...

    Trying now with that post #133 in other thread, mentioned above.
    One hiccup is with this line:
    cmake -S llvm -B build -DLLVM_ENABLE_PROJECTS="lld;clang" -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=P2 -DLLVM_TARGETS_TO_BUILD="" -DLLVM_COMPILER_JOBS="2" -Thost=x64

    Had to change llvm to ../llvm Hope that is right...

  • RaymanRayman Posts: 16,302

    Says to do this:

    To compile programs:
    Copy libp2 to Release
    Copy libp2.a to release
    

    Guess these are folders and not files? Don't have libp2.a, but do have folder libp2++...

  • RaymanRayman Posts: 16,302

    Somehow got two build folders deep...
    path=%path%;c:\opt\p2llvm\llvm-project\build\build\release\bin

  • RaymanRayman Posts: 16,302
    edited 2026-04-13 17:53

    Ok, can build, but stuck once again trying to turn .o into .elf:

    C:\opt\p2llvm\llvm-project\build\build\Release>clang --target=p2 -Wl,--gc-sections -Wl,--print-gc-sections -o t0.elf t0.o
    ld.lld: error: unable to find library -lc
    ld.lld: error: unable to find library -lp2
    ld.lld: error: cannot find linker script p2.ld
    clang: error: ld.lld command failed with exit code 1 (use -v to see invocation)
    
  • RaymanRayman Posts: 16,302

    Hmm ... Seems had same problem back in post #249 of other thread.
    Will keep reading in hopes figured it out...

  • RaymanRayman Posts: 16,302

    Ok, in post #255 or so seemed just copied the files needed, libc.a and libp2.a, from some link.
    But, that link doesn't work anymore :(

  • RaymanRayman Posts: 16,302

    Looking like libc.a and libp2.a have to be built on Linux...

    But, think should be portable to Windows, not sure...

  • roglohrogloh Posts: 6,331
    edited 2026-04-14 00:07

    The python build script should be building the libp2.a and libc.a files for you. If it can build a customized llvm application which runs under Windows it can then use that to build and archive the lib files into static libraries. I can't see what would prevent it from running on Windows unless there is some config setup error or path error etc and remember that the build directory is not the same as the install directory. That multi-level folder nesting you have for the build folder may possibly have messed things up too given the python script uses these defaults:
    DEBUG_BUILD_DIR = "llvm-project/build_debug"
    RELEASE_BUILD_DIR = "llvm-project/build_release"

    I think you might want to try to use Nikita's actual python script to install things. Windows has python3 available right?

    First you need the --configure option to create Cmake settings. Seems like you already had those and built it separately.
    Then you basically build everything, and if you do the --install option it will copy the llvm and library files it built in the build folders to the final install folder location nominated after they are built. At least that is what it does for me.

    Don't pass the --skip_libc or --skip_libp2 option or it won't build these libraries. If you already have built llvm with Visual Studio you may be able to save time and skip the llvm toolcahin building step to avoid building it again using --skip_llvm option, but you would then also need to ensure that the RELEASE_BUILD_DIR points to the correct location on your PC so it will find the built files there.

    In build.py here are the different options:

    def main():
        global build_dir
    
        parser = argparse.ArgumentParser(description='P2 LLVM Build Script')
        parser.add_argument('--configure', nargs='?', const=True, default=False)
        parser.add_argument('--skip_llvm', nargs='?', const=True, default=False)
        parser.add_argument('--skip_libc', nargs='?', const=True, default=False)
        parser.add_argument('--skip_libp2', nargs='?', const=True, default=False)
        parser.add_argument('--clean', nargs='?', const=True, default=False)
        parser.add_argument('--debug', nargs='?', const=True, default=False)
        parser.add_argument('--install', type=str, required=False)
    ...
    

    UPDATE: I just noticed you were not passing the -L option to nominate where to find the libraries in the linking step - see my prior post above.
    C:\opt\p2llvm\llvm-project\build\build\Release>clang --target=p2 -Wl,--gc-sections -Wl,--print-gc-sections -o t0.elf t0.o

    You will need to put that path in (relative to your own install folder). Without it there the linker won't know where to find these files. Also I have the p2.ld file present in the top level install folder of p2llvm and it seems to find it okay.

  • RaymanRayman Posts: 16,302

    Think one thing that is wrong is the the visual studio project that cmake creates for this is rigged for wrong compiler…

    Pretty sure these need to be built with the clang for P2…. Not sure how hard that will be change…

    Maybe one can manually compile these things and the create the .a from all the .o files?

  • RaymanRayman Posts: 16,302

    Maybe the above means that the Linux .a files should work in Windows?

    If both compiled for P2, seems should..

  • iseriesiseries Posts: 1,535

    It's been a long time since I built this project and I did not use any Linux to build it.

    Everything compiles with Visual Studio but several things have changed since then. LLVM has been upgraded to a newer version.

    I don't have my original build environment since my computer Died and had to get a new one which came with windows 11 plus had to reload most of my work. Have not reloaded this environment.

    .a files are just archive files that are built similar to .o files.

    Mike

  • roglohrogloh Posts: 6,331

    Basically @Rayman you need to do this:
    1) compile a custom LLVM using a host PC or Mac or Linux box to enable the "--target=p2" cross compiler feature in order to then compile for the P2 using it. You will first need a working native C++ compiler running on the host to do this. I used Clang on the Mac but in theory Visual Studio C++ should also be capable to build it if configured appropriately. It seems you were able to do this.
    2) use this version of LLVM to build the target libp2.a and libc.a static libraries
    3) compile projects for the P2 and link using Clang and lld (linker). For convenience the linker can be accessed indirectly via invoking Clang and passing the appropriate settings/paths to it.

    I believe some of the custom lld linker settings might get hard coded into it during build time and not everything can be setup via the command line options. Maybe some paths were setup wrong if this fails to find the locations of libraries and linker scripts.

    The entire build.py script file is meant to be able to handle this for you as it calls Cmake to build the needed libraries and (hopefully) also auto-configures it with the --configure option. However it may possibly need some customizing for Windows specific paths and tools (I'm not 100% sure as I don't have a Windows machine any more).

  • RaymanRayman Posts: 16,302

    Think see problem with Python... It's trying to invoke "make.exe", which doesn't exist...

  • roglohrogloh Posts: 6,331

    Can you find a Windows port of Make? GnuMake or something?

  • RaymanRayman Posts: 16,302

    Think will just make these .a files in Linux and then copy to windows…

  • maccamacca Posts: 1,030

    Try with msys2 https://www.msys2.org/ makes working with linux-like tools much easier on Windows.

  • RaymanRayman Posts: 16,302
    edited 2026-04-14 18:45

    Just tried with WSL and seems the Linux instructions are not good either.. Seems had to edit build.py to get anywhere...
    Built Clang, but still no luck with libs..

    Seems can't get it done in Windows or Linux :(

    Think I'll wait until there are better instructions (or somebody gifts me the .a files)...

  • roglohrogloh Posts: 6,331
    edited 2026-04-14 23:46

    You can try these .a files but they were the modified ones I use to build MicroPython based on the changes I applied using the code in the zips from this post so YMMV.
    https://forums.parallax.com/discussion/comment/1572778/#Comment_1572778
    I'm not sure if these binary archived static libraries are compatible across host platforms, hopefully they will be given the target is the same.

  • iseriesiseries Posts: 1,535

    These archive are created with the makefiles in those directories. They are clang compiled folder objects that are then packaged into an archive for consumption.

    AR = llvm-ar
    CC = clang

    Mike

  • RaymanRayman Posts: 16,302
    edited 2026-04-15 11:45

    @rogloh Those seem to make it happy. Thanks!
    Now, seems also missing p2.ld.. Searching for that now...

    686 x 440 - 35K
  • RaymanRayman Posts: 16,302

    Ok, found p2.ld... Made an elf! Guess should see if it actually works...

    707 x 218 - 15K
  • RaymanRayman Posts: 16,302
    edited 2026-04-15 12:07

    Borrowed loadp2.exe from FlexProp and it works!

    Build folder zips to 713 MB right now. This is mostly the bin output. Looks to be a lot of extraneous stuff, but hard to say. Guess will try to trim it down to essentials...

    662 x 367 - 21K
  • roglohrogloh Posts: 6,331
    edited 2026-04-15 12:27

    Good. Finally some progress. You can disassemble the code with llvm-objdump -d file.elf assuming that got built with Clang. You can also see the symbols and what got included with llvm-objdump -x file.elf.

    Strangely I did a simple hello world and it was only 24844 bytes while yours was bigger at 78112 bytes. Maybe you included a bunch of other stuff?

    ❯ cat main.c
    #include <stdio.h>
    #include <propeller.h>
    
    int main(void)
    {
    _uart_init(63,62,115200,0);
    puts("hello world\n");
    return 0;
    }
    
  • roglohrogloh Posts: 6,331

    Interestingly with this simple hello world program above I get a bunch of floating point stuff included. Presumably that is from the printf which might need to print floating point numbers?? Everything above $a00 is run from HUB RAM.

    ❯ ~/Applications/p2llvm/bin/llvm-objdump -x main.elf |grep text | sort
      1 .text         00006010 00000000 TEXT
    00000000 g     F .text  00000008 __entry
    00000040 g     F .text  00000028 __start0
    00000068 g     F .text  000000bc __start
    00000200 g     F .text  00000008 __adddf3
    00000208 g     F .text  00000008 __addsf3
    00000210 g     F .text  00000054 __ashldi3
    00000264 g     F .text  00000058 __ashrdi3
    000002bc g     F .text  00000008 __eqdf2
    000002bc g     F .text  00000008 __ledf2
    000002bc g     F .text  00000008 __ltdf2
    000002bc g     F .text  00000008 __nedf2
    000002c4 g     F .text  00000008 __gedf2
    000002c4 g     F .text  00000008 __gtdf2
    000002cc g     F .text  00000008 __unorddf2
    000002d4 g     F .text  00000008 __eqsf2
    000002d4 g     F .text  00000008 __lesf2
    000002d4 g     F .text  00000008 __ltsf2
    000002d4 g     F .text  00000008 __nesf2
    000002dc g     F .text  00000008 __gesf2
    000002dc g     F .text  00000008 __gtsf2
    000002e4 g     F .text  00000008 __unordsf2
    000002ec g     F .text  00000008 __divdi3
    000002f4 g     F .text  00000008 __divdf3
    000002fc g     F .text  00000034 __divsi3
    00000330 g     F .text  00000008 __divsf3
    00000338 g     F .text  00000008 __extendsfdf2
    00000340 g     F .text  00000008 __fixdfsi
    00000348 g     F .text  00000008 __fixsfdi
    00000350 g     F .text  00000008 __fixsfsi
    00000358 g     F .text  00000008 __fixunsdfdi
    00000360 g     F .text  00000008 __fixunsdfsi
    00000368 g     F .text  00000008 __fixunssfdi
    00000370 g     F .text  00000008 __fixunssfsi
    00000378 g     F .text  00000008 __floatdisf
    00000380 g     F .text  00000008 __floatsidf
    00000388 g     F .text  00000008 __floatundidf
    00000390 g     F .text  00000008 __floatundisf
    00000398 g     F .text  00000008 __floatunsidf
    000003a0 g     F .text  00000008 __floatunsisf
    000003a8 g     F .text  000000d8 __floatsisf
    00000480 g     F .text  00000054 __lshrdi3
    000004d4 g     F .text  00000094 memcpy
    00000568 g     F .text  00000068 memmove
    000005d0 g     F .text  00000028 memset
    000005f8 g     F .text  00000008 __moddi3
    00000600 g     F .text  00000034 __modsi3
    00000634 g     F .text  00000008 __muldf3
    0000063c g     F .text  00000008 __mulsf3
    00000644 g     F .text  00000098 __muldi3
    000006dc g     F .text  00000014 __negdi2
    000006f0 g     F .text  00000024 __subdf3
    00000714 g     F .text  00000018 __subsf3
    0000072c g     F .text  00000014 __udivdi3
    00000740 g     F .text  000000cc __udivmoddi4
    0000080c g     F .text  0000003c __umoddi3
    00000848 g     F .text  00000008 sqrtf
    00000850 g     F .text  00000008 powf
    00000a00 g     F .text  0000003c main
    00000a3c l     F .text  00000004 SimpleSerialExit
    00000a40 l     F .text  000000fc _serial_fopen
    00000b3c l     F .text  00000058 _serial_getbyte
    00000b94 l     F .text  0000002c _serial_putbyte
    00000bc0 g     F .text  000000a4 _term_write
    00000c64 g     F .text  0000017c _term_read
    00000de0 g     F .text  00000c38 __powf
    00001a18 g     F .text  00000178 ldexpf
    00001a18 g     F .text  00000178 scalbnf
    00001b90 g     F .text  00000060 fflush
    00001bf0 l     F .text  0000014c _fflush
    00001d3c g     F .text  00000110 fputc
    00001e4c g     F .text  0000009c __do_fputs
    00001ee8 g     F .text  00000028 puts
    00001f10 g     F .text  00000190 __fopen_driver
    000020a0 g     F .text  000000bc fclose
    0000215c l     F .text  00000050 _do_stdio_cleanup
    000021ac g     F .text  00000120 _InitIO
    000022cc g     F .text  000000b4 atoi
    000022cc g     F .text  000000b4 atol
    00002380 l     F .text  00000044 _run_atexit
    000023c4 g     F .text  00000008 _cstd_init
    000023cc g     F .text  00000040 _init
    0000240c g     F .text  00000040 _fini
    0000244c g     F .text  00000048 _clkset
    00002494 g     F .text  00000008 _locknew
    0000249c g     F .text  00000014 _lock
    000024b0 g     F .text  00000008 _unlock
    000024b8 g     F .text  00000078 _uart_init
    00002530 g     F .text  00000058 _uart_putc
    00002588 g     F .text  0000000c _uart_checkc
    00002594 g     F .text  00000018 _uart_getc
    000025ac l     F .text  00000668 __addXf3__
    00002c14 l     F .text  00000048 normalize
    00002c5c l     F .text  00000050 rep_clz
    00002cac l     F .text  00000380 __addXf3__
    0000302c l     F .text  00000124 __leXf2__
    00003150 l     F .text  00000128 __geXf2__
    00003278 l     F .text  00000064 __unordXf2__
    000032dc l     F .text  000000a4 __leXf2__
    00003380 l     F .text  000000a8 __geXf2__
    00003428 l     F .text  0000004c __unordXf2__
    00003474 l     F .text  000000c8 __divXi3
    0000353c l     F .text  00000914 __divXf3__
    00003e50 l     F .text  00000048 normalize
    00003e98 l     F .text  00000050 rep_clz
    00003ee8 l     F .text  0000040c __divXf3__
    000042f4 l     F .text  0000011c __extendXfYf2__
    00004410 l     F .text  000000c8 __fixint
    000044d8 l     F .text  00000114 __fixint
    000045ec l     F .text  000000a8 __fixint
    00004694 l     F .text  000000dc __fixuint
    00004770 l     F .text  000000a0 __fixuint
    00004810 l     F .text  000000b4 __fixuint
    000048c4 l     F .text  00000088 __fixuint
    0000494c g     F .text  000002e0 ___floatdisf
    00004c2c g     F .text  000000b0 ___floatsidf
    00004cdc g     F .text  00000318 ___floatundidf
    00004ff4 g     F .text  000002b4 ___floatundisf
    000052a8 g     F .text  00000080 ___floatunsidf
    00005328 g     F .text  000000b8 ___floatunsisf
    000053e0 g     F .text  00000008 __fe_getround
    000053e8 g     F .text  00000008 __fe_raise_inexact
    000053f0 l     F .text  000000e0 __modXi3
    000054d0 l     F .text  00000674 __mulXf3__
    00005b44 l     F .text  00000048 normalize
    00005b8c l     F .text  00000050 rep_clz
    00005bdc l     F .text  000002c4 __mulXf3__
    00005ea0 g     F .text  00000170 __sqrtf
    
  • RaymanRayman Posts: 16,302

    @rogloh Here are the files...

Sign In or Register to comment.