Skip to content

Commit f8b4634

Browse files
committed
build: add gen-imports to create libc.imports
This adds a python script to generate libc.imports as the shell utilities may not be available on Windows.
1 parent c71578c commit f8b4634

File tree

3 files changed

+75
-3
lines changed

3 files changed

+75
-3
lines changed

.azure-pipelines.yml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ jobs:
4848
rustup update stable --no-self-update
4949
rustup default stable
5050
rustup component add llvm-tools-preview
51-
echo "##vso[task.setvariable variable=WASM_NM;]$(rustc --print sysroot|sed 's|C:|/c|'|sed 's|\\|/|g')/lib/rustlib/x86_64-pc-windows-msvc/bin/llvm-nm.exe"
52-
displayName: Install llvm-nm (Windows)
51+
displayName: Install LLVM tools (Windows)
5352
condition: and(succeeded(), eq( variables['Agent.OS'], 'Windows_NT' ))
5453
- bash: |
5554
echo "##vso[task.setvariable variable=LLVM_AR]$(which llvm-ar)"
@@ -59,10 +58,18 @@ jobs:
5958
echo ##vso[task.setvariable variable=LLVM_AR]%CD%\citools\clang-rust\bin\llvm-ar.exe
6059
displayName: Find llvm-ar (Windows)
6160
condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'))
61+
- bash: |
62+
echo "##vso[task.setvariable variable=LLVM_NM]$(which llvm-nm)"
63+
displayName: Find llvm-nm (!Windows)
64+
condition: and(succeeded(), not(eq(variables['Agent.OS'], 'Windows_NT')))
65+
- bash: |
66+
echo "##vso[task.setvariable variable=LLVM_NM]$(rustc --print sysroot)\\lib\\rustlib\\x86_64-pc-windows-msvc\\bin\\llvm-nm.exe"
67+
displayName: Find llvm-nm (Windows)
68+
condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'))
6269
- task: CMake@1
6370
inputs:
6471
workingDirectory: $(Build.BinariesDirectory)
65-
cmakeArgs: -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_SYSTEM_NAME=Generic -DCMAKE_AR=$(LLVM_AR) -DCMAKE_C_COMPILER=clang -S $(Build.SourcesDirectory)
72+
cmakeArgs: -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_SYSTEM_NAME=Generic -DCMAKE_AR=$(LLVM_AR) -DCMAKE_NM=$(LLVM_NM) -DCMAKE_C_COMPILER=clang -S $(Build.SourcesDirectory)
6673
displayName: Configure
6774
- task: CMake@1
6875
inputs:

CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ include(CMakeDependentOption)
1111

1212
option(ENABLE_THREADS "enable threads" OFF)
1313

14+
find_package(Python COMPONENTS Interpreter REQUIRED)
15+
1416
add_compile_options(--sysroot=${CMAKE_BINARY_DIR}/sysroot)
1517

1618
# WebAssembly floating point match doesn't trap
@@ -1133,3 +1135,16 @@ foreach(stub m rt pthread crypt util xnet resolve dl)
11331135
add_custom_target(${stub} ALL
11341136
DEPENDS ${CMAKE_BINARY_DIR}/sysroot/lib/lib${stub}.a)
11351137
endforeach()
1138+
1139+
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/sysroot/lib/libc.imports
1140+
COMMAND
1141+
${Python_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/gen-imports.py
1142+
--nm ${CMAKE_NM}
1143+
--output ${CMAKE_BINARY_DIR}/sysroot/lib/libc.imports
1144+
$<TARGET_FILE:c>
1145+
${CMAKE_BINARY_DIR}/sysroot/lib/crt1.o
1146+
DEPENDS
1147+
${PROJECT_SOURCE_DIR}/tools/gen-imports.py)
1148+
add_custom_target(libc.imports ALL
1149+
DEPENDS ${CMAKE_BINARY_DIR}/sysroot/lib/libc.imports)
1150+
add_dependencies(libc.imports c crt1.o)

tools/gen-imports.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# -*- encoding: utf-8 -*-
2+
"""Generate import file for a target
3+
4+
This utility scans a static library to identify the undefined symbols which are
5+
externally visible which it expects to have provided. This is used to generate
6+
the import file definitions for WASI.
7+
8+
Example:
9+
$ python gen-imports.py --nm llvm-nm --prefix __wasi_ libc.a
10+
"""
11+
12+
import argparse
13+
import os
14+
import re
15+
import subprocess
16+
import sys
17+
18+
from subprocess import Popen
19+
20+
def main(argv):
21+
parser = argparse.ArgumentParser('gen-imports')
22+
parser.add_argument('--nm', default = 'nm')
23+
parser.add_argument('--prefix', default = '_?_wasi_')
24+
parser.add_argument('--output', required = True)
25+
26+
args, unparsed = parser.parse_known_args()
27+
28+
args.nm = os.path.normpath(args.nm)
29+
args.output = os.path.normpath(args.output)
30+
31+
process = Popen([
32+
args.nm,
33+
'--undefined-only',
34+
'--extern-only',
35+
'--just-symbol-name',
36+
] + unparsed,
37+
stdout = subprocess.PIPE)
38+
output, error = process.communicate()
39+
40+
prefix = re.compile(args.prefix)
41+
lines = output.decode('utf-8').splitlines()
42+
symbols = [ line for line in lines if not line.endswith(':') ]
43+
44+
with open(args.output, 'w') as imports:
45+
for symbol in sorted(set(symbols)):
46+
if prefix.match(symbol):
47+
imports.write('{}\n'.format(symbols))
48+
49+
if __name__ == '__main__':
50+
main(sys.argv)

0 commit comments

Comments
 (0)