Skip to content

Commit 2101787

Browse files
committed
use nix to stop fighting with llvm dependencies
1 parent b984b66 commit 2101787

14 files changed

Lines changed: 258 additions & 90 deletions

File tree

.github/workflows/ci.yml

Lines changed: 7 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -12,77 +12,13 @@ jobs:
1212
matrix:
1313
asan: [ON, OFF]
1414
build_type: [Debug, Release]
15+
os:
16+
- ubuntu-latest
17+
# - windows-latest
18+
# - macos-latest
1519

1620
steps:
17-
- name: Install LLVM
18-
run: |
19-
wget https://apt.llvm.org/llvm.sh
20-
chmod +x llvm.sh
21-
sudo ./llvm.sh ${LLVM_VERSION}
22-
23-
- name: Install other dependencies
24-
run: sudo apt-get install -y ninja-build libbenchmark-dev googletest libglm-dev doxygen libgtest-dev libzstd-dev libzstd1 libclang-${LLVM_VERSION}-dev
25-
26-
- uses: lukka/get-cmake@latest
27-
28-
- uses: actions/checkout@v4
29-
30-
- run: cmake -E make_directory build
31-
32-
- name: Configure
33-
working-directory: build
34-
run: cmake ${{ github.workspace }} -DASAN=${{ matrix.asan }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DLLVM_DIR=/usr/lib/llvm-${LLVM_VERSION}/lib/cmake/llvm -DClang_DIR=/usr/lib/llvm-${LLVM_VERSION}/lib/cmake/clang -DCOVERAGE=ON
35-
36-
- name: Build
37-
working-directory: build
38-
run: cmake --build .
39-
40-
- name: Test
41-
working-directory: build
42-
run: ctest --output-on-failure -T Test -T Coverage
43-
44-
- name: Upload coverage data (if any) to Codecov
45-
uses: codecov/codecov-action@v5
46-
with:
47-
token: ${{ secrets.CODECOV_TOKEN }}
48-
49-
build-osx:
50-
if: 0
51-
runs-on: macos-latest
52-
53-
steps:
54-
- name: Set up Homebrew
55-
uses: Homebrew/actions/setup-homebrew@master
56-
57-
- name: Install LLVM
58-
run: brew install llvm@${LLVM_VERSION}
59-
60-
- uses: lukka/get-cmake@latest
61-
6221
- uses: actions/checkout@v4
63-
64-
- run: cmake -E make_directory build
65-
66-
- name: Configure
67-
working-directory: build
68-
run: |
69-
cmake -E env LDFLAGS="-L${HOMEBREW_PREFIX}/opt/llvm@${LLVM_VERSION}/lib" \
70-
cmake ${{ github.workspace }} -DCMAKE_BUILD_TYPE=Debug \
71-
-DLLVM_DIR=${HOMEBREW_PREFIX}/opt/llvm@${LLVM_VERSION}/lib/cmake/llvm \
72-
-DClang_DIR=${HOMEBREW_PREFIX}/opt/llvm@${LLVM_VERSION}/lib/cmake/clang \
73-
-DHAVEN_BOOTSTRAP_COMPILE_FLAGS="--O2 -I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include" \
74-
-DHAVEN_COMPILE_FLAGS="--O2 -I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include" \
75-
-DCOVERAGE=ON
76-
77-
- name: Build
78-
working-directory: build
79-
run: cmake --build .
80-
81-
- name: Test
82-
working-directory: build
83-
run: ctest --output-on-failure -T Test -T Coverage
84-
85-
- name: Upload coverage data (if any) to Codecov
86-
uses: codecov/codecov-action@v5
87-
with:
88-
token: ${{ secrets.CODECOV_TOKEN }}
22+
- uses: cachix/install-nix-action@v27
23+
- run: nix build
24+
- run: nix flake check

.gitignore

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,12 @@ build-afl/
7676
# LLVM stuff
7777
*.s
7878
*.ll
79-
*.bc
79+
*.bc
80+
81+
# Output directories
82+
result/
83+
build-*/
84+
!build-etc/
85+
86+
# Fuzz stuff
87+
fuzz/findings/

CMakeLists.txt

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.28)
22
project(haven C CXX ASM)
33

44
include("CMakeDependentOption")
5+
include(CheckCCompilerFlag)
56

67
include(build-etc/config.cmake)
78
include(build-etc/macros.cmake)
@@ -10,6 +11,8 @@ find_library(MALLOC NAMES jemalloc tcmalloc)
1011

1112
find_package(LLVM REQUIRED CONFIG)
1213
find_package(Clang REQUIRED CONFIG)
14+
find_package(GTest REQUIRED)
15+
find_package(benchmark REQUIRED)
1316
find_package(Doxygen)
1417

1518
include_directories(${LLVM_INCLUDE_DIRS})
@@ -39,9 +42,13 @@ option(OTHER_MALLOC "use jemalloc or tcmalloc if present" ON)
3942
# Enable LTO?
4043
option(LTO "enable link-time optimization" OFF)
4144

45+
# C header path for Haven to use
46+
set(HAVEN_C_FLAGS "-I /usr/include" CACHE STRING "C flags to pass to Haven (e.g. for header directories)")
47+
string(REPLACE ";" " " HAVEN_C_FLAGS "${HAVEN_C_FLAGS}")
48+
4249
# Flags for compiling Haven code
43-
set(HAVEN_BOOTSTRAP_COMPILE_FLAGS "-I /usr/include --O2" CACHE STRING "flags to use when compiling Haven code with the bootstrap compiler")
44-
set(HAVEN_COMPILE_FLAGS "-I /usr/include --O2" CACHE STRING "flags to use when compiling Haven code with the main compiler")
50+
set(HAVEN_BOOTSTRAP_COMPILE_FLAGS "${HAVEN_C_FLAGS} --O2" CACHE STRING "flags to use when compiling Haven code with the bootstrap compiler")
51+
set(HAVEN_COMPILE_FLAGS "${HAVEN_C_FLAGS} --O2" CACHE STRING "flags to use when compiling Haven code with the main compiler")
4552

4653
include(build-etc/compiler.cmake)
4754

@@ -64,7 +71,10 @@ if (DOXYGEN_FOUND)
6471
doxygen_add_docs(doxygen src include)
6572
endif ()
6673

67-
# Import third-party dependencies last, so they don't interfere with our settings
68-
add_subdirectory(third_party)
69-
7074
include(CTest)
75+
76+
install(TARGETS haven havenfmt runtime
77+
RUNTIME DESTINATION bin
78+
LIBRARY DESTINATION lib
79+
ARCHIVE DESTINATION lib
80+
INCLUDES DESTINATION include)

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Matthew Iselin
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

build-etc/compiler.cmake

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,15 @@ if (UNIX AND NOT IOS AND NOT ANDROID)
3232
target_link_libraries(cmake_base_compiler_options INTERFACE -O2)
3333
endif ()
3434
else ()
35-
target_compile_options(cmake_base_compiler_options INTERFACE -O0)
36-
target_link_libraries(cmake_base_compiler_options INTERFACE -O0)
35+
# Some environments set things like _FORTIFY_SOURCE which require at least -O1
36+
check_c_compiler_flag(O0 CAN_USE_O0)
37+
if (CAN_USE_O0)
38+
target_compile_options(cmake_base_compiler_options INTERFACE -O0)
39+
target_link_libraries(cmake_base_compiler_options INTERFACE -O0)
40+
else ()
41+
target_compile_options(cmake_base_compiler_options INTERFACE -O1)
42+
target_link_libraries(cmake_base_compiler_options INTERFACE -O1)
43+
endif ()
3744
endif ()
3845

3946
if (DEBUG_SYMBOLS)

build-etc/macros.cmake

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ macro(add_bootstrap_haven_library name source)
1111

1212
add_custom_command(
1313
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
14-
COMMAND haven_bootstrap ${HAVEN_SANITIZER_FLAGS} --debug-ir --bootstrap -c ${HAVEN_BOOTSTRAP_COMPILE_FLAGS_LIST} ${CMAKE_CURRENT_SOURCE_DIR}/${source} -o ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
14+
COMMAND haven_bootstrap ${HAVEN_SANITIZER_FLAGS} --trace --debug-ir --bootstrap -c ${HAVEN_BOOTSTRAP_COMPILE_FLAGS_LIST} ${CMAKE_CURRENT_SOURCE_DIR}/${source} -o ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
1515
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/${source}
1616
DEPENDS haven_bootstrap runtime ${ARGN}
1717
COMMENT "Building ${name} from ${source} [bootstrap]"
@@ -28,7 +28,7 @@ macro(add_bootstrap_haven_executable name source)
2828

2929
add_custom_command(
3030
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
31-
COMMAND haven_bootstrap ${HAVEN_SANITIZER_FLAGS} --bootstrap -c ${HAVEN_BOOTSTRAP_COMPILE_FLAGS_LIST} ${CMAKE_CURRENT_SOURCE_DIR}/${source} -o ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
31+
COMMAND haven_bootstrap ${HAVEN_SANITIZER_FLAGS} --trace --bootstrap -c ${HAVEN_BOOTSTRAP_COMPILE_FLAGS_LIST} ${CMAKE_CURRENT_SOURCE_DIR}/${source} -o ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
3232
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/${source}
3333
DEPENDS haven_bootstrap runtime ${ARGN}
3434
COMMENT "Building ${name} from ${source} [bootstrap]"
@@ -45,7 +45,7 @@ macro(add_haven_library name source)
4545

4646
add_custom_command(
4747
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
48-
COMMAND haven ${HAVEN_SANITIZER_FLAGS} --debug-ir -c ${HAVEN_COMPILE_FLAGS_LIST} ${CMAKE_CURRENT_SOURCE_DIR}/${source} -o ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
48+
COMMAND haven ${HAVEN_SANITIZER_FLAGS} --trace --debug-ir -c ${HAVEN_COMPILE_FLAGS_LIST} ${CMAKE_CURRENT_SOURCE_DIR}/${source} -o ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
4949
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/${source}
5050
DEPENDS haven ${ARGN}
5151
COMMENT "Building ${name} from ${source}"
@@ -64,7 +64,7 @@ macro(add_haven_test_library name source optlevel)
6464
# --O${optlevel} -> set the optimization level - tests should pass at all major optimization levels
6565
add_custom_command(
6666
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
67-
COMMAND haven ${HAVEN_SANITIZER_FLAGS} --debug-ir --O${optlevel} -c ${HAVEN_COMPILE_FLAGS_LIST} ${CMAKE_CURRENT_SOURCE_DIR}/${source} -o ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
67+
COMMAND haven ${HAVEN_SANITIZER_FLAGS} --trace --debug-ir --O${optlevel} -c ${HAVEN_COMPILE_FLAGS_LIST} ${CMAKE_CURRENT_SOURCE_DIR}/${source} -o ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
6868
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/${source}
6969
DEPENDS haven ${ARGN}
7070
COMMENT "Building ${name} from ${source}"
@@ -81,7 +81,7 @@ macro(add_haven_runtime_library name source)
8181

8282
add_custom_command(
8383
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
84-
COMMAND haven_bootstrap ${HAVEN_SANITIZER_FLAGS} -c --no-preamble ${HAVEN_COMPILE_FLAGS_LIST} ${CMAKE_CURRENT_SOURCE_DIR}/${source} -o ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
84+
COMMAND haven_bootstrap ${HAVEN_SANITIZER_FLAGS} --trace -c --no-preamble ${HAVEN_COMPILE_FLAGS_LIST} ${CMAKE_CURRENT_SOURCE_DIR}/${source} -o ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
8585
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/${source}
8686
DEPENDS haven_bootstrap ${ARGN}
8787
COMMENT "Building ${name} from ${source}"

default.nix

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
stdenv,
3+
lib,
4+
cmake,
5+
pkg-config,
6+
llvmPkgs,
7+
llvmCmakeDir,
8+
callPackage,
9+
doxygen,
10+
gtest,
11+
gbenchmark,
12+
glibc,
13+
glm,
14+
...
15+
}:
16+
let
17+
project_name = "haven";
18+
stdinc_c = "${stdenv.cc.libc.dev}/include";
19+
compiler_builtins = "${llvmPkgs.clang}/resource-root/include";
20+
haven_c_flags = "-I${stdinc_c};-I${compiler_builtins}";
21+
in
22+
stdenv.mkDerivation {
23+
pname = "${project_name}";
24+
version = "1.0.0";
25+
src = ./.;
26+
nativeBuildInputs = [ cmake pkg-config llvmPkgs.clang llvmPkgs.libllvm llvmPkgs.libclang llvmPkgs.lld doxygen ];
27+
buildInputs = [ llvmPkgs.libllvm llvmPkgs.libclang llvmPkgs.clang llvmPkgs.lld gtest gbenchmark glm ];
28+
29+
cmakeFlags = [
30+
"-DLLVM_DIR=${llvmCmakeDir}"
31+
"-DHAVEN_C_FLAGS=${lib.escapeShellArg haven_c_flags}"
32+
];
33+
34+
checkPhase = ''
35+
echo "Running CTest..."
36+
ctest --output-on-failure
37+
'';
38+
39+
doCheck = true;
40+
}

flake.lock

Lines changed: 60 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
description = "The Haven programming language";
3+
4+
inputs = {
5+
nixpkgs.url = "github:NixOS/nixpkgs";
6+
flake-utils.url = "github:numtide/flake-utils";
7+
};
8+
9+
outputs = { self, nixpkgs, flake-utils }:
10+
flake-utils.lib.eachDefaultSystem (system:
11+
let
12+
pkgs = import nixpkgs { inherit system; };
13+
llvmPkgs = pkgs.llvmPackages_18;
14+
llvmCmakeDir = "${llvmPkgs.libllvm.dev}/lib/cmake/llvm";
15+
haven = pkgs.callPackage ./default.nix { inherit llvmPkgs llvmCmakeDir; stdenv = llvmPkgs.stdenv; };
16+
in {
17+
apps.default = {
18+
type = "app";
19+
program = "${haven}/bin/haven";
20+
meta = with pkgs.lib; {
21+
description = "The Haven programming language";
22+
license = licenses.mit;
23+
};
24+
};
25+
26+
packages.default = haven;
27+
28+
devShells.default = pkgs.mkShell {
29+
nativeBuildInputs = with pkgs; [ cmake ninja pkg-config llvmPkgs.clang llvmPkgs.libllvm llvmPkgs.lld gtest gbenchmark doxygen ];
30+
CMAKE_PREFIX_PATH = llvmCmakeDir;
31+
};
32+
});
33+
}

include/compiler.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ int compiler_deserialize_and_codegen(struct compiler *compiler, char *buffer, si
104104
// the target platform, e.g. "c" -> "-lc"
105105
void compiler_add_link_library(struct compiler *compiler, const char *lib);
106106

107+
// Convert compiler flags into a form useful for cimport
108+
// Caller must free entries and the result pointer here.
109+
const char *const *compiler_get_cimport_compiler_flags(struct compiler *compiler, size_t *count);
110+
107111
void destroy_compiler(struct compiler *compiler);
108112

109113
__attribute__((__format__(__printf__, 3, 0))) int compiler_vdiag(struct compiler *compiler,

0 commit comments

Comments
 (0)