# I want to write a CMake script for building a web application.

**URL:** https://discourse.cmake.org/t/i-want-to-write-a-cmake-script-for-building-a-web-application/15880
**Category:** Code
**Tags:** os:linux, gen:ninja
**Created:** [October 19, 2026, 8:16am UTC](https://discourse.cmake.org/t/i-want-to-write-a-cmake-script-for-building-a-web-application/15880 "2026-10-19T08:16:16Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![amagi](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9d8465/32.png) [@amagi](https://discourse.cmake.org/u/amagi)
#### Post date: [October 19, 2026, 8:16am UTC](https://discourse.cmake.org/t/i-want-to-write-a-cmake-script-for-building-a-web-application/15880/1 "2026-10-19T08:16:17Z")

</div>

# Description

I’m trying to build a C++ project using raylib and glm for a web application, but I don’t know how to resolve the error shown in the terminal log below.

## What I’ve Tried

I searched through the raylib samples, copied and pasted the code, and ran it → Same error  
URL: [loading...](https://www.raylib.com/examples/core/loader.html?name=core_window_web)

Implemented using Gemini → Encountered the error shown in the log

With the provided CMake file, I was able to build and run the project before adding the lines for the web version, so  
the error is caused by those additions.

The libraries I’m using are raylib and glm. I downloaded them from GitHub, built them, and installed them.

The directory is `/home/amagi/clones/raylib/src/raylib`, but I navigated to my home directory  
by typing `cd home/amagi/clones/raylib/src/` and used `ls` to confirm the presence of `raylib.a`. However, for some reason,  
I’m still getting the same error.

I also added `#include` at the top of the source file, but I’m still getting the same error.

## What I Want to Know

I want to know how to resolve the issue shown in the console log and how to write the CMake file correctly.

# Terminal log

```auto
 ~/dev/top-down/build ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 2m 58s ─╮
╰─❯ emcmake cmake .. ─╯
    cmake --build .
configure: cmake .. -DCMAKE_TOOLCHAIN_FILE=/usr/share/emscripten/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_CROSSCOMPILING_EMULATOR=/usr/bin/node
-- Configuring done (0.5s)
-- Generating done (0.0s)
-- Build files have been written to: /home/amagi/dev/top-down/build
gmake[2]: ***'app.html' に必要なターゲット '/home/amagi/clones/raylib/src/raylib' を make するルールがありません. 中止.
gmake[1]: *** [CMakeFiles/Makefile2:87: CMakeFiles/app.dir/all] エラー 2
gmake: *** [Makefile:91: all] エラー 2

```

## translate to english from japanese

```auto
gmake[2]: *** There is no rule to build the target ‘/home/amagi/clones/raylib/src/raylib’ required by ‘app.html’. Aborting.
gmake[1]: *** [CMakeFiles/Makefile2:87: CMakeFiles/app.dir/all] Error 2
gmake: *** [Makefile:91: all] Error 2

```

# CMakeLists.txt

```auto
cmake_minimum_required(VERSION 3.16)

# compiler
set(CMAKE_CXX_COMPILER "clang++")
set(CMAKE_C_COMPILER "clang")

# project
set(PROJECT_NAME "app")

set(CMAKE_CXX_STANDARD 26)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

set(PROJECT_VERSION "1.0.0")
project(${PROJECT_NAME} VERSION ${PROJECT_VERSION})

#####################################################################
# Project
#####################################################################

set(EXE_NAME ${PROJECT_NAME})
set(EXE_SOURCE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/src")
set(EXE_INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/include")

#file(GLOB_RECURSE EXE_SOURCE_LIST CONFIGURE_DEPENDS "${EXE_SOURCE_PATH}/*.cpp" "${EXE_SOURCE_PATH}/*.c")

set(EXE_SOURCE_LIST
    "${EXE_SOURCE_PATH}/Main.cpp"
)

add_executable(${EXE_NAME} ${EXE_SOURCE_LIST})

target_precompile_headers(${PROJECT_NAME} PRIVATE
    # <glm/glm.hpp>
    # <box2d/box2d.h>
    # <entt/entt.hpp>
    <vector>
    <variant>
    <iostream>
    <memory>
)

# ==========================================
# Emscripten
# ==========================================
if(EMSCRIPTEN)
    # 1. 出力ファイルの拡張子を .html にする
    set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".html")

    target_link_libraries(${EXE_NAME} PRIVATE "$ENV{HOME}/clones/raylib/src/raylib")
    target_link_libraries(${EXE_NAME} PRIVATE "$ENV{HOME}/clones/glm/build/glm/glm")

target_include_directories(${EXE_NAME} PRIVATE "${EXE_INCLUDE_PATH}" "$ENV{HOME}/clones/glm" "$ENV{HOME}/clones/raylib/src/")

    # 2. 必要なリンクオプション（ご提示のコマンドに対応）
    target_link_options(${PROJECT_NAME} PRIVATE
        -sUSE_GLFW=3
        -sASYNCIFY
        -sINITIAL_MEMORY=67108864 # ※近代的なEmscriptenでは TOTAL_MEMORY より INITIAL_MEMORY が推奨されます
        -O2
        # シェルファイルを指定する場合
        # "--shell-file" "${CMAKE_CURRENT_SOURCE_DIR}/shell.html"

        # アセット（resourcesフォルダなど）を同梱する場合
        # "--preload-file" "${CMAKE_CURRENT_SOURCE_DIR}/resources@resources"
    )
endif()

target_link_libraries(${EXE_NAME} PRIVATE "$ENV{HOME}/clones/raylib/src/raylib")
target_link_libraries(${EXE_NAME} PRIVATE "$ENV{HOME}/clones/glm/build/glm/glm")
# target_link_libraries(${EXE_NAME} PRIVATE "glm")
# target_link_libraries(${EXE_NAME} PRIVATE "box2d")

target_link_libraries(${EXE_NAME} PRIVATE "GL")
target_link_libraries(${EXE_NAME} PRIVATE "m")
target_link_libraries(${EXE_NAME} PRIVATE "pthread")
target_link_libraries(${EXE_NAME} PRIVATE "dl")
target_link_libraries(${EXE_NAME} PRIVATE "rt")
target_link_libraries(${EXE_NAME} PRIVATE "X11")

```

# Main.cpp

```cpp

#include "raylib.h"
#include "glm/glm.hpp"

#if defined(PLATFORM_WEB)
    #include <emscripten/emscripten.h>
#endif

//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
int screenWidth = 800;
int screenHeight = 450;

//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
void UpdateDrawFrame(void); // Update and Draw one frame

//----------------------------------------------------------------------------------
// Program main entry point
//----------------------------------------------------------------------------------
int main(void)
{
    // Initialization
    //--------------------------------------------------------------------------------------
    InitWindow(screenWidth, screenHeight, "raylib [core] example - window web");

#if defined(PLATFORM_WEB)
    emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
#else
    SetTargetFPS(60); // Set our game to run at 60 frames-per-second
    //--------------------------------------------------------------------------------------

    // Main game loop
    while (!WindowShouldClose()) // Detect window close button or ESC key
    {
        UpdateDrawFrame();
    }
#endif

    // De-Initialization
    //--------------------------------------------------------------------------------------
    CloseWindow(); // Close window and OpenGL context
    //--------------------------------------------------------------------------------------

    return 0;
}

//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
void UpdateDrawFrame(void)
{
    // Update
    //----------------------------------------------------------------------------------
    // TODO: Update your variables here
    //----------------------------------------------------------------------------------

    // Draw
    //----------------------------------------------------------------------------------
    BeginDrawing();

        ClearBackground(RAYWHITE);

        DrawText("Welcome to raylib web structure!", 220, 200, 20, SKYBLUE);

    EndDrawing();
    //----------------------------------------------------------------------------------
}

```

---

<div class="post-metadata">

### Author: ![retif](https://discourse.cmake.org/user_avatar/discourse.cmake.org/retif/32/1776_2.png) [@retif](https://discourse.cmake.org/u/retif)
#### Post date: [October 19, 2026, 8:52am UTC](https://discourse.cmake.org/t/i-want-to-write-a-cmake-script-for-building-a-web-application/15880/2 "2026-10-19T08:52:04Z")

</div>

The `target_link_libraries()` should (_ideally_) operate with targets, but instead you are providing a path (_to a folder?_). And even before that the target should be discovered first with something like `find_package(raylib CONFIG REQUIRED)` (_perhaps without `CONFIG`_), depending on how this dependency is resolved in your system.

But you claim that it works with “non-web” version, and I can’t say why it is so.

---

<div class="post-metadata">

### Author: ![amagi](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9d8465/32.png) [@amagi](https://discourse.cmake.org/u/amagi)
#### Post date: [October 19, 2026, 10:47am UTC](https://discourse.cmake.org/t/i-want-to-write-a-cmake-script-for-building-a-web-application/15880/3 "2026-10-19T10:47:41Z")

</div>

Thank you.  
Based on what I’ve looked into, it seems I need a .a file built for the web, so I ran the following commands to create it. Since the system installation is for the desktop,  
I deliberately left it in the `clones/` directory and did not install it.  
I adjusted the path, deleted the `build` directory, and ran the same commands, but I still got the same error.

```auto
cd raylib
emcmake cmake . -DPLATFORM=Web
emmake make

```
