Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ jobs:
-DCLANG_TIDY_CACHE=/data/tidy-cache \
-DGPU_TARGETS=gfx908 \
..
make -j$(nproc) -k onnx-proto tf-proto tidy
make -j$(nproc) -k onnx-proto tf-proto generate_api tidy

# GH actions can not update existing cache, as a workaround clear cache and then save it
- name: Clear tidy cache before saving
Expand Down
47 changes: 44 additions & 3 deletions src/api/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#####################################################################################
# The MIT License (MIT)
#
# Copyright (c) 2015-2025 Advanced Micro Devices, Inc. All rights reserved.
# Copyright (c) 2015-2026 Advanced Micro Devices, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
Expand All @@ -22,9 +22,50 @@
# THE SOFTWARE.
#####################################################################################

# The C API (migraphx.h and api.cpp) is generated from the templates in
# tools/api. `make generate` still writes them into the source tree so the
# output can be reviewed, but migraphx_c is built from a freshly generated copy
# placed in the build directory instead of the checked-in src/api copies.
find_package(Python 3 COMPONENTS Interpreter REQUIRED)

set(MIGRAPHX_API_TOOLS_DIR ${PROJECT_SOURCE_DIR}/tools)
set(MIGRAPHX_API_GEN_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/include)
set(MIGRAPHX_API_GEN_HEADER ${MIGRAPHX_API_GEN_INCLUDE_DIR}/migraphx/migraphx.h)
set(MIGRAPHX_API_GEN_SOURCE ${CMAKE_CURRENT_BINARY_DIR}/api.cpp)

# generate.py writes migraphx.h under include/migraphx/ and api.cpp at the top
# level of the output dir, mirroring the source-tree layout. The build copy is
# only a compiler input, so it is generated without clang-format; `make
# generate` still formats the reviewable source-tree copy.
add_custom_command(
OUTPUT ${MIGRAPHX_API_GEN_HEADER} ${MIGRAPHX_API_GEN_SOURCE}
COMMAND ${Python_EXECUTABLE} ${MIGRAPHX_API_TOOLS_DIR}/generate.py
--api-only
--api-output-dir ${CMAKE_CURRENT_BINARY_DIR}
WORKING_DIRECTORY ${MIGRAPHX_API_TOOLS_DIR}
DEPENDS
${MIGRAPHX_API_TOOLS_DIR}/generate.py
${MIGRAPHX_API_TOOLS_DIR}/api.py
${MIGRAPHX_API_TOOLS_DIR}/api/migraphx.h
${MIGRAPHX_API_TOOLS_DIR}/api/api.cpp
${CMAKE_CURRENT_SOURCE_DIR}/migraphx.py
COMMENT "Generating C API (migraphx.h and api.cpp) in build directory"
VERBATIM
)

add_custom_target(generate_api DEPENDS ${MIGRAPHX_API_GEN_HEADER} ${MIGRAPHX_API_GEN_SOURCE})

# migraphx.hpp is hand-written (not generated); copy it next to the generated
# migraphx.h so the build include directory is a complete public API.
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/include/migraphx/migraphx.hpp
${MIGRAPHX_API_GEN_INCLUDE_DIR}/migraphx/migraphx.hpp
COPYONLY)

add_library(migraphx_c
api.cpp
${MIGRAPHX_API_GEN_SOURCE}
)
add_dependencies(migraphx_c generate_api)
set_target_properties(migraphx_c PROPERTIES EXPORT_NAME c)
migraphx_generate_export_header(migraphx_c DIRECTORY migraphx/api)

Expand All @@ -43,5 +84,5 @@ target_link_libraries(migraphx_c PUBLIC migraphx_version)
rocm_install_targets(
TARGETS migraphx_c
INCLUDE
${CMAKE_CURRENT_SOURCE_DIR}/include
${MIGRAPHX_API_GEN_INCLUDE_DIR}
)
70 changes: 51 additions & 19 deletions tools/generate.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#####################################################################################
# The MIT License (MIT)
#
# Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved.
# Copyright (c) 2015-2026 Advanced Micro Devices, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -41,40 +41,72 @@ def clang_format(buffer, **kwargs):
**kwargs).stdout.decode('utf-8')


def api_generate(input_path: Path, output_path: Path):
def maybe_format(buffer, do_format=True):
return clang_format(buffer) if do_format else buffer


def api_generate(input_path: Path, output_path: Path, do_format=True):
output_path.parent.mkdir(parents=True, exist_ok=True)
with open(output_path, 'w') as f:
f.write(clang_format(api.run(input_path)))
f.write(maybe_format(api.run(input_path), do_format))


def te_generate(input_path: Path, output_path: Path):
def te_generate(input_path: Path, output_path: Path, do_format=True):
with open(output_path, 'w') as f:
f.write(clang_format(te.run(input_path)))
f.write(maybe_format(te.run(input_path), do_format))


def generate_api(output_dir: Path, do_format=True):
runpy.run_path(str(migraphx_py_path))
header_path = output_dir / 'include/migraphx/migraphx.h'
source_path = output_dir / 'api.cpp'
api_generate(work_dir / 'api/migraphx.h', header_path, do_format)
print(f'Finished generating header {header_path}')
api_generate(work_dir / 'api/api.cpp', source_path, do_format)
print(f'Finished generating source {source_path}')


def generate_all(do_format=True):
files = Path('include').absolute().iterdir()
for f in [f for f in files if f.is_file()]:
te_generate(f, src_dir / f'include/migraphx/{f.name}', do_format)
generate_api(src_dir / 'api', do_format)


def main():
parser = argparse.ArgumentParser()
parser.add_argument('-f', '--clang-format', type=Path)
parser.add_argument('--api-only',
action='store_true',
help='Only generate the C API files (migraphx.h and '
'api.cpp) under the directory given by '
'--api-output-dir instead of writing into the source '
'tree')
parser.add_argument('--api-output-dir',
type=Path,
help='Base output directory for the generated C API '
'files: migraphx.h is written under include/migraphx/ '
'and api.cpp at the top level')
args = parser.parse_args()

if args.api_only and not args.api_output_dir:
parser.error('--api-only requires --api-output-dir')

global clang_format_path
if args.clang_format:
clang_format_path = args.clang_format

if not clang_format_path.is_file():
print(f"{clang_format_path}: invalid path or not installed",
file=sys.stderr)
return

try:
files = Path('include').absolute().iterdir()
for f in [f for f in files if f.is_file()]:
te_generate(f, src_dir / f'include/migraphx/{f.name}')
runpy.run_path(str(migraphx_py_path))
api_generate(work_dir / 'api/migraphx.h',
src_dir / 'api/include/migraphx/migraphx.h')
print('Finished generating header migraphx.h')
api_generate(work_dir / 'api/api.cpp', src_dir / 'api/api.cpp')
print('Finished generating source api.cpp')
if args.api_only:
# These files are only consumed by the compiler, so skip
# clang-format; only `make generate` formats them for review.
generate_api(args.api_output_dir, do_format=False)
else:
if not clang_format_path.is_file():
print(f"{clang_format_path}: invalid path or not installed",
file=sys.stderr)
return
generate_all()
except subprocess.CalledProcessError as ex:
if ex.stdout:
print(ex.stdout.decode('utf-8'))
Expand Down
Loading